package com.netrust.quarz.utils;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * @CopyRight：http://www.netrust.cn/
 *
 * @Description:日期操作公共辅助类   
 * @Author: lazite 
 * @CreateTime: 2015年11月15日 下午2:41:38   
 * @ModifyBy: lazite 
 * @ModeifyTime: 2015年11月15日 下午2:41:38   
 * @ModifyDescription:
 * @Version:   V1.0
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils{

	private static Logger logger=LoggerFactory.getLogger(DateUtils.class);
    /**
     * 默认格式
     */
    public static final String FORMAT_DEFAULT = "yyyy-MM-dd HH:mm:ss";
    
    public static final String FORMAT_DEFAULT_ = "yyyy/MM/dd HH:mm:ss";
    
    public static final String FORMAT_DEFAULT_1 = "yyyy-MM-dd";
    
    public static final String FORMAT_TIME = "yyyy-MM-dd HH:mm:ss:SS ";
    public static final String FORMAT_TIME_3 = "yyyy-MM-dd HH:mm:ss.SSS ";

    public static final String COMPARE_DAY = "day";

    public static final String COMPARE_TIME = "time";

    /**
     * 默认格式化对象
     */
    public static final SimpleDateFormat SIMPLE_DATE_FORMAT_DEFAULT = new SimpleDateFormat(FORMAT_DEFAULT);

    /**
     * 获取当前时间微妙数
     *
     * @return
     * @throws Exception
     */
    public static long getCurrentDateTime() throws Exception {
        return new Date().getTime();
    }

    /**
     * 获取当前时间
     *
     * @return
     * @throws Exception
     */
    public static Date getCurrentDate() throws Exception {
        return new Date();
    }

    /**
     * 按照指定格式格式化当前时间
     *
     * @return
     * @throws Exception
     */
    public static String getCurrentDateString() throws Exception {
        return SIMPLE_DATE_FORMAT_DEFAULT.format(new Date());
    }

    /**
     * 按照指定格式格式化当前时间
     *
     * @param format
     * @return
     * @throws Exception
     */
    public static String getCurrentDateString(String format) throws Exception {
        return getSimpleDateFormat(format).format(new Date());
    }

    /**
     * 获取格式化对象
     *
     * @param format
     * @return
     * @throws Exception
     */
    public static SimpleDateFormat getSimpleDateFormat(String format) throws Exception {
        if (StringUtils.isNotBlank(format)) {
            return new SimpleDateFormat(format);
        }
        return SIMPLE_DATE_FORMAT_DEFAULT;
    }

    /**
     * 将String转Date
     *
     * @param date
     * @param format
     * @return
     * @throws Exception
     */
    public static Date getDateFormString(String date, String format) throws Exception {
        return getSimpleDateFormat(format).parse(date);
    }

    /**
     * 将时间字符串从格式A到格式B
     *
     * @param date
     * @param oldFormat
     * @param newFormat
     * @return
     * @throws Exception
     */
    public static String getStringFormDateString(String date, String oldFormat, String newFormat) throws Exception {
        return getSimpleDateFormat(newFormat).format(getSimpleDateFormat(oldFormat).parse(date));
    }

    /**
     * 将JDBC日期形式的字符串转换成日期形式。
     *
     * @param dateString JDBC日期形式的字符串（yyyy-MM-dd);
     * @return 日期：Jun 10, 2011
     */
    public static java.sql.Date getDateByString(String dateString) throws Exception {
        if (dateString == null || "".equals(dateString)) {
            return (java.sql.Date) new Date();
        }
        java.sql.Date date = java.sql.Date.valueOf(dateString);
        return date;
    }
    
   
    /**
     * 将日期格式 2011-03-09格式转换成2011年3月9日
     *
     * @param date
     * @return 日期：Jun 13, 2011
     */
    public static String transformChinaDateform(java.sql.Date date) throws Exception {
        if (date == null) {
            return "";
        }

        String dateString = date.toString();
        String[] dateStrings = dateString.split("-");

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(dateStrings[0]);
        stringBuilder.append("年");
        stringBuilder.append(dateStrings[1]);
        stringBuilder.append("月");
        stringBuilder.append(dateStrings[2]);
        stringBuilder.append("日");

        return stringBuilder.toString();
    }

    /**
     * Use default format to convert string to date.
     *
     * @param dateTxt
     * @return Date
     */
    public static Date parseDate(String dateTxt) {
        return parseDate(dateTxt, FORMAT_DEFAULT);
    }
    
    /**
     * 
     * @Title: parseDate
     * @param date
     * @return
     */
    public static Timestamp parseDate(Date date) {
    	return Timestamp.valueOf(formatDate(date, FORMAT_DEFAULT));
    }
    
    /**
     * 
     * @Title: parseDate
     * @param timestamp
     * @return
     */
    public static Date parseDate(Timestamp ts) {
    	 Date date = new Date();
    	 try {   
             date = ts;   
         } catch (Exception e) {   
             logger.error("Parse Date Error: " + e.getMessage());
             return null;
         }  
    	return date;
    }
    
    /**
     * @param dateTxt
     * @param format
     * @return Date
     */
    public static Date parseDate(String dateTxt, String format) {
        SimpleDateFormat sf = new SimpleDateFormat(format);
        sf.setLenient(false);
        try {
            return sf.parse(dateTxt);
        } catch (Exception e) {
            logger.error("Parse Date Error: " + e.getMessage());
            return null;
        }
    }

    public static Date parseDate(Date date, String format) {
        String dateTxt = formatDate(date, format);
        return parseDate(dateTxt, format);
    }
    
    /**
	 * 日期型字符串转化为日期 格式
	 * { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", 
	 *   "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm",
	 *   "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm" }
	 */
	private static String[] parsePatterns = {
			"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", 
			"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
			"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
	public static Date parseDate(Object str) {
		if (str == null){
			return null;
		}
		try {
			return parseDate(str.toString(), parsePatterns);
		} catch (ParseException e) {
			return null;
		}
	}

	/**
	 * 获取过去的天数
	 * @param date
	 * @return
	 */
	public static long pastDays(Date date) {
		long t = new Date().getTime()-date.getTime();
		return t/(24*60*60*1000);
	}

	/**
	 * 获取过去的小时
	 * @param date
	 * @return
	 */
	public static long pastHour(Date date) {
		long t = new Date().getTime()-date.getTime();
		return t/(60*60*1000);
	}
	
	/**
	 * 获取过去的分钟
	 * @param date
	 * @return
	 */
	public static long pastMinutes(Date date) {
		long t = new Date().getTime()-date.getTime();
		return t/(60*1000);
	}
    
    /**
     * @param date
     * @return String
     */
    public static String formatDate(Date date) {
        return formatDate(date, FORMAT_DEFAULT);
    }
    
    public static String formatDate_(Date date) {
        return formatDate(date, FORMAT_DEFAULT_);
    }
    
    public static String formatDate_1(Date date) {
        return formatDate(date, FORMAT_DEFAULT_1);
    }
	/**
	 * 得到日期时间字符串，转换格式（yyyy-MM-dd HH:mm:ss）
	 */
	public static String formatDateTime(Date date) {
		return formatDate(date, "yyyy-MM-dd HH:mm:ss");
	}
	/**
	 * 转换为时间（天,时:分:秒.毫秒）
	 * @param timeMillis
	 * @return
	 */
    public static String formatDateTime(long timeMillis){
		long day = timeMillis/(24*60*60*1000);
		long hour = (timeMillis/(60*60*1000)-day*24);
		long min = ((timeMillis/(60*1000))-day*24*60-hour*60);
		long s = (timeMillis/1000-day*24*60*60-hour*60*60-min*60);
		long sss = (timeMillis-day*24*60*60*1000-hour*60*60*1000-min*60*1000-s*1000);
		return (day>0?day+",":"")+hour+":"+min+":"+s+"."+sss;
    }
    /**
     * @param date
     * @param format
     * @return String
     */
    public static String formatDate(Date date, String format) {
        if (date == null) {
            logger.debug("Date not formatted. Date is null.");
            return "";
        }
        SimpleDateFormat sf = new SimpleDateFormat(format);
        return sf.format(date);
    }

    public static Date addMins(Date date, int mins) {
        if (date == null)
            return null;
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MINUTE, mins);
        return cal.getTime();

    }

    /**
     * Get current year . e.g 2010, If the date is invaild then return -1.
     *
     * @return int
     */
    public static int getCurrentYear() {
        Calendar cal = Calendar.getInstance();
        return cal.get(Calendar.YEAR);
    }

    public static Date setCurrentyear(Date date) {
        if (date == null)
            return null;
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.YEAR, getCurrentYear());
        return cal.getTime();
    }

    /**
     * Get the year of the specified Dated
     *
     * @param date
     * @return int
     */
    public static int getYear(Date date) {
        if (date == null)
            return -1;
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.YEAR);

    }

    /**
     * @param dateTxt
     * @return int
     */
    public static int getYear(String dateTxt) {
        Date date = parseDate(dateTxt);
        return getYear(date);
    }

    /**
     * @param dateTxt
     * @return int
     */
    public static int getYear(String dateTxt, String format) {
        Date date = parseDate(dateTxt, format);
        return getYear(date);
    }
    
	/**
	 * 得到当前日期字符串 格式（yyyy-MM-dd）
	 */
	public static String getDate() {
		return getDate("yyyy-MM-dd");
	}
	
	/**
	 * 得到当前日期字符串 格式（yyyy-MM-dd） pattern可以为："yyyy-MM-dd" "HH:mm:ss" "E"
	 */
	public static String getDate(String pattern) {
		return DateFormatUtils.format(new Date(), pattern);
	}
    
    public static Date addMonths(Date date, int months) {
        if (date == null) {
            logger.error("DateUtil.addYears . Date is null.");
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, months);
        return cal.getTime();
    }

    /**
     * @param date
     * @return int
     */
    public static int getWeek(Date date) {
        if (date == null)
            return -1;
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int week = cal.get(Calendar.DAY_OF_WEEK) - 1;
        return week == 0 ? 7 : week;
    }

    /**
     * @param dateTxt e.g. 01/12/2010
     * @return int
     */
    public static int getWeek(String dateTxt) {
        Date date = parseDate(dateTxt);
        return getWeek(date);
    }

    /**
     * @param date
     * @return int
     */
    public static int getMonth(Date date) {
        if (date == null)
            return -1;
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.MONTH) + 1;
    }

    /**
     * @param dateTxt e.g. 01/12/2010
     * @return int
     */
    public static int getMonth(String dateTxt) {
        Date date = parseDate(dateTxt);
        return getMonth(date);
    }

    /**
     * @param dateTxt
     * @param format
     * @return int
     */
    public static int getMonth(String dateTxt, String format) {
        Date date = parseDate(dateTxt, format);
        return getMonth(date);
    }

    /**
     * @param date
     * @return int
     */
    public static int getDay(Date date) {
        if (date == null)
            return -1;
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * @param dateTxt
     * @return int
     */
    public static int getDay(String dateTxt) {
        Date date = parseDate(dateTxt);
        return getDay(date);
    }

    /**
     * @param dateTxt
     * @param format
     * @return int
     */
    public static int getDay(String dateTxt, String format) {
        Date date = parseDate(dateTxt, format);
        return getDay(date);
    }

    /**
     * Check if the date string whether is valid .
     *
     * @param dateTxt
     * @return boolean
     */
    public static boolean isDateValid(String dateTxt) {
        Date date = parseDate(dateTxt);
        if (date == null)
            return false;
        return true;
    }

    /**
     * @param dateTxt
     * @param format
     * @return boolean
     */
    public static boolean isDateValid(String dateTxt, String format) {
        Date date = parseDate(dateTxt, format);
        if (date == null)
            return false;
        return true;
    }

    /**
     * Check the format is valid
     *
     * @param dateTxt
     * @return boolean
     */
    public static boolean isFormatValid(String dateTxt) {
        // \\d{2}-\\d{2}-\\d{4}
        if (dateTxt == null || dateTxt.trim().length() == 0) {
            return false;
        }
        if (dateTxt.trim().length() != 10)
            return false;
        String[] strs = dateTxt.split("-");
        if (strs == null || strs.length != 3)
            return false;
        if (strs[0].length() == 2 && strs[1].length() == 2 && strs[2].length() == 4) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * @param date
     * @param years
     * @return Date
     */
    public static Date addYears(Date date, int years) {
        if (date == null) {
            logger.error("DateUtil.addYears . Date is null.");
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.YEAR, years);
        return cal.getTime();
    }

    /**
     * @param date
     * @param days
     * @return Date
     */
    public static Date addDays(Date date, int days) {
        if (date == null) {
            logger.error("DateUtil.addYears . Date is null.");
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DAY_OF_YEAR, days);
        return cal.getTime();
    }

    /**
     * If the day==1 means Saturday, day==7 means Sunday
     *
     * @param date
     * @return int
     */
    public static int getDayOfWeek(Date date) {
        if (date == null) {
            logger.error("DateUtil.addYears . Date is null.");
            return -1;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_WEEK);
    }

    /**
     * @param date
     * @return boolean
     */
    public static boolean isWeekend(Date date) {
        int dayOfWeek = getDayOfWeek(date);
        return dayOfWeek == 1 || dayOfWeek == 7;
    }

    /**
     * Return the day gap between two dates. Default calculate is include today
     *
     * @param fromDate
     * @param toDate
     * @return long
     */
    public static long getDayGap(Date fromDate, Date toDate) {
        return getDayGap(fromDate, toDate, true);
    }

    /**
     * @param fromDate
     * @param toDate
     * @return long
     */
    public static long getDayGap(Date fromDate, Date toDate, boolean includeToday) {
        /*
		 * Calendar cal = Calendar.getInstance(); cal.setTime(fromDate); int
		 * day1 = cal.get(Calendar.DAY_OF_YEAR); cal.setTime(toDate); int day2 =
		 * cal.get(Calendar.DAY_OF_YEAR); return includeToday?(day2-day1)+1 :
		 * (day2-day1);
		 */
        long day = (toDate.getTime() - fromDate.getTime()) / 1000 / 3600 / 24;
        return includeToday ? day + 1 : day;
    }

    public static long getDayGap(long fromDate, long toDate, boolean includeToday) {
		/*
		 * Calendar cal = Calendar.getInstance(); cal.setTime(fromDate); int
		 * day1 = cal.get(Calendar.DAY_OF_YEAR); cal.setTime(toDate); int day2 =
		 * cal.get(Calendar.DAY_OF_YEAR); return includeToday?(day2-day1)+1 :
		 * (day2-day1);
		 */
        long day = (toDate - fromDate) / 1000 / 3600 / 24;
        return includeToday ? day + 1 : day;
    }

    public static int getMonthGap(Date fromDate, Date toDate) {
        return (getYear(toDate) - getYear(fromDate)) * 12 + (getMonth(toDate) - getMonth(fromDate));
    }

    /**
     * @param date1 <String>
     * @param date2 <String>
     * @return int
     */
    public static int getMonthSpace(String date1, String date2) {
        int result = 0;
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(parseDate(date1, "yyyy-MM-dd"));
        c2.setTime(parseDate(date2, "yyyy-MM-dd"));
        result = c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH);
        return Math.abs(result);
    }

    public static boolean isNumDaysBefore(Date referDate, Date compareDate, int days) {
        if (isAfter(referDate, compareDate)) {
            return false;
        }
        Date newDate = addDays(compareDate, days);
        return isEqual(referDate, newDate);
    }

    public static boolean isNumDaysAfter(Date referDate, Date compareDate, int days) {
        if (isBefore(referDate, compareDate)) {
            return false;
        }
        Date newDate = addDays(referDate, days);
        return isEqual(newDate, compareDate);
    }

    /**
     * Compare two dates, if COMPARE_DAY then compare two dates ignore time. If
     * COMPARE_TIME, then will compare two dates with time.
     */
    /**
     * ********************** Compare date 1 before date 2
     * ********************************
     */
    public static boolean isBefore(Date referDate, Date compareDate) {
        return isBefore(referDate, compareDate, COMPARE_DAY);
    }

    public static boolean isBefore(Date referDate, Date compareDate, String compareStyle) {
        return before(referDate, compareDate, false, compareStyle);
    }

    public static boolean isBeforeOrEqual(Date referDate, Date compareDate) {
        return isBeforeOrEqual(referDate, compareDate, COMPARE_DAY);
    }

    public static boolean isBeforeOrEqual(Date referDate, Date compareDate, String compareStyle) {
        return before(referDate, compareDate, true, compareStyle);
    }

    /**
     * ********************** Compare date 1 after date 2
     * ********************************
     */

    public static boolean isAfter(Date referDate, Date compareDate) {
        return isAfter(referDate, compareDate, COMPARE_DAY);
    }

    public static boolean isAfter(Date referDate, Date compareDate, String compareStyle) {
        return after(referDate, compareDate, false, compareStyle);
    }

    public static boolean isAfterOrEqual(Date referDate, Date compareDate) {
        return isAfterOrEqual(referDate, compareDate, COMPARE_DAY);
    }

    public static boolean isAfterOrEqual(Date referDate, Date compareDate, String compareStyle) {
        return after(referDate, compareDate, true, compareStyle);
    }

    /**
     * ********************** Compare date 1 and date 2 at the same day
     * ********************************
     */

    public static boolean isEqual(Date referDate, Date compareDate) {
        return isEqual(referDate, compareDate, COMPARE_DAY);
    }

    public static boolean isEqual(Date referDate, Date compareDate, String compareStyle) {
        if (!COMPARE_DAY.equals(compareStyle) && !COMPARE_TIME.equals(compareStyle)) {
            logger.error("Can't identify compare way. Use compare day as default");
            compareStyle = COMPARE_DAY;
        }
        if (COMPARE_TIME.equals(compareStyle)) {
            return compareDate.getTime() == referDate.getTime();
        }

        if (COMPARE_DAY.equals(compareStyle)) {
            Calendar referCal = Calendar.getInstance();
            referCal.setTime(referDate);

            Calendar compareCal = Calendar.getInstance();
            compareCal.setTime(compareDate);
            if (compareCal.get(Calendar.YEAR) != referCal.get(Calendar.YEAR))
                return false;
            if (compareCal.get(Calendar.MONTH) != referCal.get(Calendar.MONTH))
                return false;
            if (compareCal.get(Calendar.DAY_OF_YEAR) != referCal.get(Calendar.DAY_OF_YEAR))
                return false;
            return true;
        }

        return false;
    }

    public static boolean isBetween(Date fromDate, Date toDate, Date compareDate) {
        return isBetween(fromDate, toDate, compareDate, COMPARE_DAY);
    }

    public static boolean isBetween(Date fromDate, Date toDate, Date compareDate, String compareStyle) {
        if (compareDate == null) {
            return false;
        }
        assert fromDate != null : "From Date is null";
        assert toDate != null : "To date is null";
        if (isBeforeOrEqual(toDate, compareDate, compareStyle) && isAfterOrEqual(fromDate, compareDate, compareStyle)) {
            return true;
        } else {
            return false;
        }

    }

    private static boolean before(Date referDate, Date compareDate, boolean allowEqual, String compareStyle) {
        // assert referDate!=null : "Param referDate cannot be null.";
        // assert compareDate!=null : "Param compareDate cannot be null.";
        if (referDate == null || compareDate == null) {
            logger.error("+++++ DateUtil.before .Refer Date and Compare Date should not be null. +++++");
        } else {
            if (!COMPARE_DAY.equals(compareStyle) && !COMPARE_TIME.equals(compareStyle)) {
                logger.error("Can't identify compare way. Use compare day as default");
                compareStyle = COMPARE_DAY;
            }
            if (COMPARE_TIME.equals(compareStyle)) {
                return compareDate.getTime() < referDate.getTime();
            }

            if (COMPARE_DAY.equals(compareStyle)) {
                Calendar referCal = Calendar.getInstance();
                referCal.setTime(referDate);

                Calendar compareCal = Calendar.getInstance();
                compareCal.setTime(compareDate);
                if (compareCal.get(Calendar.YEAR) < referCal.get(Calendar.YEAR)) {
                    return true;
                } else {
                    if (compareCal.get(Calendar.YEAR) > referCal.get(Calendar.YEAR)) {
                        return false;
                    }
                    if (compareCal.get(Calendar.MONTH) < referCal.get(Calendar.MONTH)) {
                        return true;
                    } else {
                        if (compareCal.get(Calendar.MONTH) > referCal.get(Calendar.MONTH)) {
                            return false;
                        }
                        if (allowEqual) {
                            return compareCal.get(Calendar.DAY_OF_YEAR) <= referCal.get(Calendar.DAY_OF_YEAR);
                        }
                        return compareCal.get(Calendar.DAY_OF_YEAR) < referCal.get(Calendar.DAY_OF_YEAR);
                    }
                }
            }

        }

        return false;
    }

    private static boolean after(Date referDate, Date compareDate, boolean allowEqual, String compareStyle) {
        if (!COMPARE_DAY.equals(compareStyle) && !COMPARE_TIME.equals(compareStyle)) {
            logger.error("Can't identify compare way. Use compare day as default");
            compareStyle = COMPARE_DAY;
        }
        if (COMPARE_TIME.equals(compareStyle)) {
            return compareDate.getTime() > referDate.getTime();
        }

        if (COMPARE_DAY.equals(compareStyle)) {
            Calendar referCal = Calendar.getInstance();
            referCal.setTime(referDate);

            Calendar compareCal = Calendar.getInstance();
            compareCal.setTime(compareDate);
            if (compareCal.get(Calendar.YEAR) > referCal.get(Calendar.YEAR)) {
                return true;
            } else {
                if (compareCal.get(Calendar.YEAR) < referCal.get(Calendar.YEAR)) {
                    return false;
                }
                if (compareCal.get(Calendar.MONTH) > referCal.get(Calendar.MONTH)) {
                    return true;
                } else {
                    if (compareCal.get(Calendar.MONTH) < referCal.get(Calendar.MONTH)) {
                        return false;
                    }
                    if (allowEqual) {
                        return compareCal.get(Calendar.DAY_OF_YEAR) >= referCal.get(Calendar.DAY_OF_YEAR);
                    }
                    return compareCal.get(Calendar.DAY_OF_YEAR) > referCal.get(Calendar.DAY_OF_YEAR);
                }
            }
        }

        return false;
    }

    public static int getStudentAge(Date bod, Date screenDate) {
        if (bod == null || screenDate == null) {
            logger.error("ERROR in DateUtil.getStudentAge BOD:" + bod + " , ScreenDate:" + screenDate);
            return -1;
        }

        int month = getMonthGap(bod, screenDate);
        Calendar bodCal = Calendar.getInstance();
        Calendar screenCal = Calendar.getInstance();

        bodCal.setTime(bod);
        screenCal.setTime(screenDate);

        if (bodCal.get(Calendar.DAY_OF_MONTH) > screenCal.get(Calendar.DAY_OF_MONTH)) {
            month--;
        }

        return month;
    }

    public static boolean isOneWeek(Date date1, Date date2) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date1);// 设置日期
        int a = ca.get(Calendar.WEEK_OF_YEAR);// 获取一年中的周数
        int year1 = ca.get(Calendar.YEAR);
        ca.setTime(date2);
        int b = ca.get(Calendar.WEEK_OF_YEAR);
        int year2 = ca.get(Calendar.YEAR);
        if (year1 == year2 && a == b)
            return true;
        else
            return false;
    }

    /**
     * 得到本月的第一天
     *
     * @return
     */
    public static String getMonthFirstDay() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, calendar
                .getActualMinimum(Calendar.DAY_OF_MONTH));

        return formatDate(calendar.getTime(), "yyyy-MM-dd");
    }

    /**
     * 得到本月的最后一天
     *
     * @return
     */
    public static String getMonthLastDay() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, calendar
                .getActualMaximum(Calendar.DAY_OF_MONTH));
        return formatDate(calendar.getTime(), "yyyy-MM-dd");
    }
    
    
    /**
     * 得到某年某周的第一天
     *
     * @param year
     * @param week
     * @return
     */
    public static Date getFirstDayOfWeek(int year, int week) {
        week = week - 1;
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, Calendar.JANUARY);
        calendar.set(Calendar.DATE, 1);

        Calendar cal = (Calendar) calendar.clone();
        cal.add(Calendar.DATE, week * 7);

        return getFirstDayOfWeek(cal.getTime());
    }

    /**
     * 得到某年某周的最后一天
     *
     * @param year
     * @param week
     * @return
     */
    public static Date getLastDayOfWeek(int year, int week) {
        week = week - 1;
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, Calendar.JANUARY);
        calendar.set(Calendar.DATE, 1);
        Calendar cal = (Calendar) calendar.clone();
        cal.add(Calendar.DATE, week * 7);

        return getLastDayOfWeek(cal.getTime());
    }

    /**
     * 取得当前日期所在周的第一天
     *
     * @param date
     * @return
     */
    public static Date getFirstDayOfWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.SUNDAY);
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_WEEK,
                      calendar.getFirstDayOfWeek()); // Sunday
        return calendar.getTime();
    }

    /**
     * 取得当前日期所在周的最后一天
     *
     * @param date
     * @return
     */
    public static Date getLastDayOfWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.SUNDAY);
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_WEEK,
                     calendar.getFirstDayOfWeek() + 6); // Saturday
        return calendar.getTime();
    }

    /**
     * 取得当前日期所在周的前一周最后一天
     *
     * @param date
     * @return
     */
    public static Date getLastDayOfLastWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return getLastDayOfWeek(calendar.get(Calendar.YEAR),
                                calendar.get(Calendar.WEEK_OF_YEAR) - 1);
    }

    /**
     * 返回指定日期的月的第一天
     *
     * @param year
     * @param month
     * @return
     */
    public static Date getFirstDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(calendar.get(Calendar.YEAR),
                     calendar.get(Calendar.MONTH), 1);
        return calendar.getTime();
    }

    /**
     * 返回指定年月的月的第一天
     *
     * @param year
     * @param month
     * @return
     * @throws Exception 
     */
    public static Date getFirstDayOfMonth(Integer year, Integer month) throws Exception {
        Calendar calendar = Calendar.getInstance();
        if (year == null) {
            year = calendar.get(Calendar.YEAR);
        }
        if (month == null) {
            month = calendar.get(Calendar.MONTH);
        }
        calendar.set(year, month-1, 1);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String day = year+"-"+month+"-"+01+" 00:00:01";
        return sdf.parse(day);
    }

    /**
     * 返回指定日期的月的最后一天
     *
     * @param year
     * @param month
     * @return
     */
    public static Date getLastDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(calendar.get(Calendar.YEAR),
                     calendar.get(Calendar.MONTH), 1);
        calendar.roll(Calendar.DATE, -1);
        return calendar.getTime();
    }

    /**
     * 返回指定年月的月的最后一天
     *
     * @param year
     * @param month
     * @return
     */
    public static Date getLastDayOfMonth(Integer year, Integer month) {
        Calendar calendar = Calendar.getInstance();
        if (year == null) {
            year = calendar.get(Calendar.YEAR);
        }
        if (month == null) {
            month = calendar.get(Calendar.MONTH);
        }
        calendar.set(year, month, 1);
        calendar.roll(Calendar.DATE, -1);
        return calendar.getTime();
    }

    /**
     * 返回指定日期的上个月的最后一天
     *
     * @param year
     * @param month
     * @return
     */
    public static Date getLastDayOfLastMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(calendar.get(Calendar.YEAR),
                     calendar.get(Calendar.MONTH) - 1, 1);
        calendar.roll(Calendar.DATE, -1);
        return calendar.getTime();
    }

    /**
     * 返回指定日期的季的第一天
     *
     * @param year
     * @param quarter
     * @return
     */
    public static Date getFirstDayOfQuarter(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return getFirstDayOfQuarter(calendar.get(Calendar.YEAR),
                                    getQuarterOfYear(date));
    }

    /**
     * 返回指定年季的季的第一天
     *
     * @param year
     * @param quarter
     * @return
     */
    public static Date getFirstDayOfQuarter(Integer year, Integer quarter) {
      
        try {
        	  Calendar calendar = Calendar.getInstance();
              Integer month = new Integer(0);
              if (quarter == 1) {
                  month = 1 - 1;
              } else if (quarter == 2) {
                  month = 4 - 1;
              } else if (quarter == 3) {
                  month = 7 - 1;
              } else if (quarter == 4) {
                  month = 10 - 1;
              } else {
                  month = calendar.get(Calendar.MONTH);
              }
			return getFirstDayOfMonth(year, month);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
    }

    /**
     * 返回指定日期的季的最后一天
     *
     * @param year
     * @param quarter
     * @return
     */
    public static Date getLastDayOfQuarter(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return getLastDayOfQuarter(calendar.get(Calendar.YEAR),
                                   getQuarterOfYear(date));
    }

    /**
     * 返回指定年季的季的最后一天
     *
     * @param year
     * @param quarter
     * @return
     */
    public static Date getLastDayOfQuarter(Integer year, Integer quarter) {
        Calendar calendar = Calendar.getInstance();
        Integer month = new Integer(0);
        if (quarter == 1) {
            month = 3 - 1;
        } else if (quarter == 2) {
            month = 6 - 1;
        } else if (quarter == 3) {
            month = 9 - 1;
        } else if (quarter == 4) {
            month = 12 - 1;
        } else {
            month = calendar.get(Calendar.MONTH);
        }
        return getLastDayOfMonth(year, month);
    }

    /**
     * 返回指定日期的上一季的最后一天
     *
     * @param year
     * @param quarter
     * @return
     */
    public static Date getLastDayOfLastQuarter(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return getLastDayOfLastQuarter(calendar.get(Calendar.YEAR),
                                       getQuarterOfYear(date));
    }

    /**
     * 返回指定年季的上一季的最后一天
     *
     * @param year
     * @param quarter
     * @return
     */
    public static Date getLastDayOfLastQuarter(Integer year, Integer quarter) {
        Calendar calendar = Calendar.getInstance();
        Integer month = new Integer(0);
        if (quarter == 1) {
            month = 12 - 1;
        } else if (quarter == 2) {
            month = 3 - 1;
        } else if (quarter == 3) {
            month = 6 - 1;
        } else if (quarter == 4) {
            month = 9 - 1;
        } else {
            month = calendar.get(Calendar.MONTH);
        }
        return getLastDayOfMonth(year, month);
    }

    /**
     * 返回指定日期的季度
     *
     * @param date
     * @return
     */
    public static int getQuarterOfYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH) / 3 + 1;
    }

   /* public static void main(String[] args) {
		 System.out.println("Current Year :"+DateUtil.getCurrentYear());
		  System.out.println("Date1: "+DateUtil.formatDate(new Date()));
		 * System.out.println("Date2: "+DateUtil.formatDate(new
		 * Date(),"dd/MM/yyyy"));
		 * System.out.println("ParseDate1:"+DateUtil.parseDate
		 * ("2010/09/01 20:12:11").toString());
		 * System.out.println("ParseDate1:"+
		 * DateUtil.parseDate("2010/09/01 20:12:11","dd/MM/yyyy").toString());
		 
        Date date1 = DateUtil.parseDate("29-08-2010");
        Date date2 = DateUtil.parseDate("05-10-2011");

        // System.out.println(DateUtil.getMonth(date1));
        System.out.println(DateUtil.getMonthGap(date1, date2));
        System.out.println(DateUtil.getStudentAge(date1, date2));
        // System.out.println(DateUtil.getDayGap(date1, date2,false));
		
		 * System.out.println(DateUtil.isBefore(date1, date2));
		 * System.out.println(DateUtil.isBeforeOrEqual(date1, date2));
		 * System.out.println(DateUtil.isAfter(date1, date2));
		 * System.out.println(DateUtil.isAfterOrEqual(date1, date2));
		 * System.out.println(DateUtil.isEqual(date1, date2));
		 * System.out.println(DateUtil.isEqual(date1,
		 * date2,DateUtil.COMPARE_TIME));
		 * System.out.println(DateUtil.parseDate("2011-04-09 12:00:00"
		 * ,"yyyy-MM-dd HH:mm:ss")); System.out.println(DateUtil.formatDate(new
		 * Date(),"yyyy-MM-dd HH:mm:ss"));
		 
        // Date date=new Date();
        // System.out.println(date);
        // System.out.println(DateUtil.addMins(date, 30));
        // System.out.println(DateUtil.addMins(date, 40));
        // System.out.println(DateUtil.addMins(date, 60));
		
		 * System.out.println(DateUtil.isNumDaysBefore(DateUtil.parseDate(
		 * "01-06-2011"), new Date(), 2));
		 * System.out.println(DateUtil.isNumDaysBefore
		 * (DateUtil.parseDate("14-06-2011"), new Date(), 2));
		 * System.out.println
		 * (DateUtil.isNumDaysBefore(DateUtil.parseDate("15-06-2011"), new
		 * Date(), 2));
		 * System.out.println(DateUtil.isNumDaysBefore(DateUtil.parseDate
		 * ("16-06-2011"), new Date(), 2));
		 * System.out.println(DateUtil.isNumDaysBefore
		 * (DateUtil.parseDate("17-06-2011"), new Date(), 2));
		 * System.out.println
		 * (DateUtil.isNumDaysBefore(DateUtil.parseDate("18-06-2011"), new
		 * Date(), 2));
		 * System.out.println(DateUtil.isNumDaysBefore(DateUtil.parseDate
		 * ("19-06-2011"), new Date(), 2));
		 
        System.out.println(getWeek(new Date(new Date().getTime() - 1000 * 24 * 3600 * 1)));
        System.out.println(getDayGap(new Date(), new Date(new Date().getTime() - 1000 * 24 * 3600 * 5)));

    }*/
    
    
    //获取当天的开始时间
    public static java.util.Date getDayBegin() {
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }
    //获取当天的结束时间
    public static java.util.Date getDayEnd() {
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal.getTime();
    }
    
    //获取某一天的开始时间
    public static java.util.Date getDayBegin(Date date) {
    	Calendar cal = Calendar.getInstance();
    	cal.setTime(date);
    	
    	cal.set(Calendar.HOUR_OF_DAY, 0);
    	cal.set(Calendar.MINUTE, 0);
    	cal.set(Calendar.SECOND, 0);
    	cal.set(Calendar.MILLISECOND, 0);
    	return cal.getTime();
    }
    //获取当天的结束时间
    public static java.util.Date getDayEnd(Date date) {
    	Calendar cal = Calendar.getInstance();
    	cal.setTime(date);
    	
    	cal.set(Calendar.HOUR_OF_DAY, 23);
    	cal.set(Calendar.MINUTE, 59);
    	cal.set(Calendar.SECOND, 59);
    	return cal.getTime();
    }
    //获取昨天的开始时间
    public static Date getBeginDayOfYesterday() {
        Calendar cal = new GregorianCalendar();
        cal.setTime(getDayBegin());
        cal.add(Calendar.DAY_OF_MONTH, -1);
        return cal.getTime();
    }
    //获取昨天的结束时间
    public static Date getEndDayOfYesterDay() {
        Calendar cal = new GregorianCalendar();
        cal.setTime(getDayEnd());
        cal.add(Calendar.DAY_OF_MONTH, -1);
        return cal.getTime();
    }
    //获取明天的开始时间
    public static Date getBeginDayOfTomorrow() {
        Calendar cal = new GregorianCalendar();
        cal.setTime(getDayBegin());
        cal.add(Calendar.DAY_OF_MONTH, 1);

        return cal.getTime();
    }
    //获取明天的结束时间
    public static Date getEndDayOfTomorrow() {
        Calendar cal = new GregorianCalendar();
        cal.setTime(getDayEnd());
        cal.add(Calendar.DAY_OF_MONTH, 1);
        return cal.getTime();
    }
    //获取本周的开始时间
    public static Date getBeginDayOfWeek() {
        Date date = new Date();
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
        if (dayofweek == 1) {
            dayofweek += 7;
        }
        cal.add(Calendar.DATE, 2 - dayofweek);
        return getDayStartTime(cal.getTime());
    }
    //获取本周的结束时间
    public static Date getEndDayOfWeek(){
        Calendar cal = Calendar.getInstance();
        cal.setTime(getBeginDayOfWeek());  
        cal.add(Calendar.DAY_OF_WEEK, 6); 
        Date weekEndSta = cal.getTime();
        return getDayEndTime(weekEndSta);
    }
    //获取本月的开始时间
     public static Date getBeginDayOfMonth() {
            Calendar calendar = Calendar.getInstance();
            calendar.set(getNowYear(), getNowMonth() - 1, 1);
            return getDayStartTime(calendar.getTime());
        }
    //获取本月的结束时间
     public static Date getEndDayOfMonth() {
            Calendar calendar = Calendar.getInstance();
            calendar.set(getNowYear(), getNowMonth() - 1, 1);
            int day = calendar.getActualMaximum(5);
            calendar.set(getNowYear(), getNowMonth() - 1, day);
            return getDayEndTime(calendar.getTime());
        }
     //获取本年的开始时间
     public static java.util.Date getBeginDayOfYear() {
            Calendar cal = Calendar.getInstance();
            cal.set(Calendar.YEAR, getNowYear());
            // cal.set
            cal.set(Calendar.MONTH, Calendar.JANUARY);
            cal.set(Calendar.DATE, 1);

            return getDayStartTime(cal.getTime());
        }
     //获取本年的结束时间
     public static java.util.Date getEndDayOfYear() {
            Calendar cal = Calendar.getInstance();
            cal.set(Calendar.YEAR, getNowYear());
            cal.set(Calendar.MONTH, Calendar.DECEMBER);
            cal.set(Calendar.DATE, 31);
            return getDayEndTime(cal.getTime());
        }
    //获取某个日期的开始时间
    public static Timestamp getDayStartTime(Date d) {
        Calendar calendar = Calendar.getInstance();
        if(null != d) calendar.setTime(d);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),    calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return new Timestamp(calendar.getTimeInMillis());
    }
    //获取某个日期的结束时间
    public static Timestamp getDayEndTime(Date d) {
        Calendar calendar = Calendar.getInstance();
        if(null != d) calendar.setTime(d);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),    calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return new Timestamp(calendar.getTimeInMillis());
    }
    //获取今年是哪一年
     public static Integer getNowYear() {
             Date date = new Date();
            GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
            gc.setTime(date);
            return Integer.valueOf(gc.get(1));
        }
     //获取本月是哪一月
     public static int getNowMonth() {
             Date date = new Date();
            GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
            gc.setTime(date);
            return gc.get(2) + 1;
        }
     //两个日期相减得到的天数
     public static int getDiffDays(Date beginDate, Date endDate) {

            if (beginDate == null || endDate == null) {
                throw new IllegalArgumentException("getDiffDays param is null!");
            }

            long diff = (endDate.getTime() - beginDate.getTime())
                    / (1000 * 60 * 60 * 24);

            int days = new Long(diff).intValue();

            return days;
        }
    //两个日期相减得到的毫秒数
     public static long dateDiff(Date beginDate, Date endDate) {
            long date1ms = beginDate.getTime();
            long date2ms = endDate.getTime();
            return date2ms - date1ms;
        }
     //获取两个日期中的最大日期
     public static Date max(Date beginDate, Date endDate) {
            if (beginDate == null) {
                return endDate;
            }
            if (endDate == null) {
                return beginDate;
            }
            if (beginDate.after(endDate)) {
                return beginDate;
            }
            return endDate;
        }
     //获取两个日期中的最小日期
     public static Date min(Date beginDate, Date endDate) {
            if (beginDate == null) {
                return endDate;
            }
            if (endDate == null) {
                return beginDate;
            }
            if (beginDate.after(endDate)) {
                return endDate;
            }
            return beginDate;
        }
     //返回某月该季度的第一个月
     public static Date getFirstSeasonDate(Date date) {
             final int[] SEASON = { 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4 };
            Calendar cal = Calendar.getInstance();
            cal.setTime(date);
            int sean = SEASON[cal.get(Calendar.MONTH)];
            cal.set(Calendar.MONTH, sean * 3 - 3);
            return cal.getTime();
        }
     //返回某个日期下几天的日期
     public static Date getNextDay(Date date, int i) {
            Calendar cal = new GregorianCalendar();
            cal.setTime(date);
            cal.set(Calendar.DATE, cal.get(Calendar.DATE) + i);
            return cal.getTime();
        }
     //返回某个日期前几天的日期
     public static Date getFrontDay(Date date, int i) {
            Calendar cal = new GregorianCalendar();
            cal.setTime(date);
            cal.set(Calendar.DATE, cal.get(Calendar.DATE) - i);
            return cal.getTime();
        }
     //获取某年某月到某年某月按天的切片日期集合（间隔天数的日期集合）
     public static List getTimeList(int beginYear, int beginMonth, int endYear,
                int endMonth, int k) {
            List list = new ArrayList();
            if (beginYear == endYear) {
                for (int j = beginMonth; j <= endMonth; j++) {
                    list.add(getTimeList(beginYear, j, k));

                }
            } else {
                {
                    for (int j = beginMonth; j < 12; j++) {
                        list.add(getTimeList(beginYear, j, k));
                    }

                    for (int i = beginYear + 1; i < endYear; i++) {
                        for (int j = 0; j < 12; j++) {
                            list.add(getTimeList(i, j, k));
                        }
                    }
                    for (int j = 0; j <= endMonth; j++) {
                        list.add(getTimeList(endYear, j, k));
                    }
                }
            }
            return list;
        }
     //获取某年某月按天切片日期集合（某个月间隔多少天的日期集合）
     public static List getTimeList(int beginYear, int beginMonth, int k) {
            List list = new ArrayList();
            Calendar begincal = new GregorianCalendar(beginYear, beginMonth, 1);
            int max = begincal.getActualMaximum(Calendar.DATE);
            for (int i = 1; i < max; i = i + k) {
                list.add(begincal.getTime());
                begincal.add(Calendar.DATE, k);
            }
            begincal = new GregorianCalendar(beginYear, beginMonth, max);
            list.add(begincal.getTime());
            return list;
        }
}
